package xcmg.device.service.account;

import com.github.pagehelper.PageInfo;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.account.ArapDO;
import xcmg.device.dao.entity.account.ArapDetailDO;
import xcmg.device.dao.entity.account.InvoiceDO;
import xcmg.device.dao.entity.company.CompanyDealerDO;
import xcmg.device.dao.entity.company.DealerVehicleDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDetailDO;
import xcmg.device.dao.entity.prepPay.PrepPayDO;
import xcmg.device.dao.entity.sale.SalesBillDO;
import xcmg.device.dao.mapper.CompanyDealerMapper;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.account.ArapDetailMapper;
import xcmg.device.dao.mapper.account.ArapMapper;
import xcmg.device.dao.mapper.account.InvoiceDetailMapper;
import xcmg.device.dao.mapper.company.DealerVehicleMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteDetailMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteMapper;
import xcmg.device.dao.mapper.sale.SalesBillMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.enums.SaleOutEnum;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.account.ArapDetailVO;
import xcmg.device.service.vo.account.ArapVO;
import xcmg.device.service.vo.account.CheckVO;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@Service
public class ArapService {

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private CompanyDealerMapper companyDealerMapper;

    @Autowired
    private ArapMapper arapMapper;

    @Autowired
    private ArapDetailMapper arapDetailMapper;

    @Autowired
    private DeliveryNoteMapper deliveryNoteMapper;

    @Autowired
    private DeliveryNoteDetailMapper deliveryNoteDetailMapper;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private InvoiceDetailMapper invoiceDetailMapper;
    @Autowired
    private DealerVehicleMapper dealerVehicleMapper;
    @Autowired
    private SalesBillMapper salesBillMapper;
    @Autowired
    private CompanyInfoMapper companyInfoMapper;
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode addArap(List<Map<String, String>> dataList, String orgId)throws Exception{
        if(ListUtil.isNullOrEmpty(dataList)){
            return ErrorCode.IllegalArument;
        }
        CompanyDealerDO dealerDO;
        ArapDO arapDO;
        String dealerCode;
        BigDecimal thisPrice;
        for(Map<String, String> dataMap : dataList){
            dealerCode = dataMap.get("KUNRG");
            thisPrice = dataMap.get("thisPrice")==null?BigDecimal.ZERO:new BigDecimal(dataMap.get("thisPrice"));
            dealerDO = companyDealerMapper.itemByDealerCode(orgId, dealerCode);
            if(dealerDO == null){
                LogHelper.error("付款方 (客户编码)不存在，"+dealerCode, ErrorCode.Failure.getCode());
                continue;
            }
            arapDO = arapMapper.selectByAccOrgId(orgId, dealerDO.getDealerOrgId(), 0);
            if(arapDO == null){
                arapDO = new ArapDO();
                arapDO.setId(fastGenClient.textGuid().getValue());
                arapDO.setOrgId(orgId);
                arapDO.setAccOrgId(dealerDO.getDealerOrgId());
                arapDO.setAccOrgName(dealerDO.getCompanyName());
                arapDO.setDealerCode(dealerDO.getDealerCode());
                arapDO.setArapType(0);
                arapDO.setReceiverPrice(thisPrice);
                arapDO.setCreateDate(new Date());
                arapMapper.insert(arapDO);
            }else{
                arapDO.setReceiverPrice(arapDO.getReceiverPrice().add(thisPrice));
                arapDO.setUpdateDate(new Date());
                arapMapper.update(arapDO);
            }
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode addArapDetail(List<Map<String, String>> dataList, String orgId)throws Exception{
        if(ListUtil.isNullOrEmpty(dataList)){
            return ErrorCode.IllegalArument;
        }
        String deliveryOutNo;
        String materialNo;
        BigDecimal price;
        DeliveryNoteDO deliveryNoteDO;
        ArapDetailDO arapDetailDO;
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
        for(Map<String, String> dataMap : dataList){
            deliveryOutNo = dataMap.get("JHDANCODE");
            materialNo = dataMap.get("MATNR");
            if(StringUtil.isNullOrEmpty(deliveryOutNo)){
                LogHelper.error("发货通知单单号不存在", ErrorCode.Failure.getCode());
                continue;
            }
            deliveryNoteDO = deliveryNoteMapper.findBySapOutNo(deliveryOutNo, orgId);
            if(deliveryNoteDO == null){
                LogHelper.error("未能根据发货通知单单号找到单据，"+deliveryOutNo, ErrorCode.Failure.getCode());
                continue;
            }
            //更新发货通知单开票状态和开票时间
            deliveryNoteMapper.updateTicketState(deliveryNoteDO.getId(), sdf.parse(dataMap.get("FKDAT")),sdf.parse(dataMap.get("ERDAT")));

            DeliveryNoteDetailDO noteDetailDO = deliveryNoteDetailMapper.itemByMaterialsNo(deliveryNoteDO.getId(), materialNo);
            if(noteDetailDO == null){
                LogHelper.error("未找到零件详情，"+deliveryOutNo+"，"+materialNo, ErrorCode.Failure.getCode());
                continue;
            }
            price = new BigDecimal(dataMap.get("KZWI1"));
            dataMap.put("thisPrice", price+"");

            arapDetailDO = arapDetailMapper.selectByBillNo(orgId, deliveryNoteDO.getDeliveryNo());
            if(arapDetailDO == null){
                arapDetailDO = new ArapDetailDO();
                arapDetailDO.setId(fastGenClient.textGuid().getValue());
                arapDetailDO.setSupplierOrgId(orgId);
                arapDetailDO.setSupplierOrgName(deliveryNoteDO.getSupplierOrgName());
                arapDetailDO.setPurchaseOrgId(deliveryNoteDO.getPurchaseOrgId());
                arapDetailDO.setPurchaseOrgName(deliveryNoteDO.getPurchaseOrgName());
                arapDetailDO.setDeliveryOutNo(deliveryNoteDO.getSapOutNo());
                arapDetailDO.setBillId(deliveryNoteDO.getId());
                arapDetailDO.setBillNo(deliveryNoteDO.getDeliveryNo());
                arapDetailDO.setBillDate(deliveryNoteDO.getCreateDate());
                arapDetailDO.setBillSingle(StringUtils.left(deliveryNoteDO.getDeliveryNo(), 4));
                arapDetailDO.setTotalPrice(price);
                arapDetailDO.setRemainPrice(price);
                arapDetailDO.setCreateDate(new Date());
                arapDetailMapper.insert(arapDetailDO);
            }else{
                arapDetailDO.setTotalPrice(arapDetailDO.getTotalPrice().add(price));
                arapDetailDO.setRemainPrice(arapDetailDO.getTotalPrice().subtract(arapDetailDO.getReceivePrice()));
                arapDetailDO.setUpdateDate(new Date());
                arapDetailMapper.update(arapDetailDO);
            }
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode cancel(InvoiceDO invoiceDO)throws Exception{
        ArapDO arapDO = arapMapper.selectByAccOrgId(invoiceDO.getOrgId(), invoiceDO.getPayerOrgId(), 0);
        boolean success;
        if(arapDO != null){
            arapDO.setReceiverPrice(arapDO.getReceiverPrice().subtract(invoiceDO.getPrice()));
             success = arapMapper.update(arapDO)>0;
            if(!success){
                throw new Exception("更新应收记录失败");
            }
        }
        List<String> deliveryNos = invoiceDetailMapper.findDeliveryNo(invoiceDO.getInvoiceNo(), invoiceDO.getOrgId());
        if (!CollectionUtils.isEmpty(deliveryNos)) {
            success = arapDetailMapper.updateDel(invoiceDO.getOrgId(), deliveryNos)>0;
            if(!success){
                throw new Exception("更新应收记录失败");
            }
        }
        return ErrorCode.Success;
    }

    public PageCommonVO list(SearchCommonVO<ArapVO> condition) {
        PageCommonVO result = new PageCommonVO();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<ArapDO> doList = arapMapper.list(condition.getFilters());
        ArapDO arapDO = arapMapper.selectTotalReceive(condition.getFilters());
        if (arapDO == null) {
            arapDO = new ArapDO();
        }
        List<ArapVO> voList = new ArrayList<>();
        for (ArapDO entity : doList) {
            ArapVO model = new ArapVO();
            BeanUtils.copyProperties(entity, model);
            model.setTotalReceiverPrice(arapDO.getReceiverPrice());
            model.setTotalPrepReceiverPrice(arapDO.getPrepReceiverPrice());
            model.setTotalPrepPayPrice(arapDO.getPrepPayPrice());
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    public PageCommonVO detailList(SearchCommonVO<ArapDetailVO> condition,String orgId){
        PageCommonVO result = new PageCommonVO();
        ArapDetailVO arapDetailVO = condition.getFilters();
        //获取当前用户的isSap
        /*CompanyInfoDO companyInfoDO = companyInfoMapper.item(orgId);
        if (null != companyInfoDO && null != companyInfoDO.getIsSap()  && 0 == companyInfoDO.getIsSap()){
            arapDetailVO.setBillSingle(BillDesc.SalesOutNo.getDesc());
        }
*/
        PageHelperPlus.orderBy("BILL_DATE desc");
        if(condition.getFilters().getIsAll() == null){
            PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        }
        List<ArapDetailDO> doList = arapDetailMapper.list(arapDetailVO);
        List<ArapDetailVO> voList = new ArrayList<>();
        for (ArapDetailDO entity : doList) {
            ArapDetailVO model = new ArapDetailVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    public void export(List<String> ids)throws Exception{
        PageHelperPlus.orderBy("create_date desc");
        invokeExport(arapMapper.findByIds(ids));
    }

    public void exportAll(ArapVO condition)throws Exception{
        Integer count = arapMapper.listCount(condition);
        List<ArapDO> dataList = new ArrayList<>();
        int times = count/500+1;
        for(int i=0; i<times; i++){
            PageHelperPlus.startPage(i + 1, 500, "create_date desc");
            dataList.addAll(arapMapper.list(condition));
        }
        invokeExport(dataList);
    }

    private void invokeExport(List<ArapDO> doList)throws Exception{
        String title = "应收应付代理商数据导出";
        String[] rowsName = new String[]{"序号","客户名称","预收款金额","应收款金额"};
        List<Object[]>  dataList = new ArrayList<Object[]>();
        Object[] objs;
        BigDecimal receiverPrice = BigDecimal.ZERO;
        BigDecimal preReceiverPrice = BigDecimal.ZERO;
        for (int i = 0; i < doList.size(); i++) {
            ArapDO exportDO = doList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i+1;
            objs[1] = exportDO.getAccOrgName();
            objs[2] = exportDO.getPrepReceiverPrice();
            objs[3] = exportDO.getReceiverPrice();
            dataList.add(objs);

            receiverPrice = receiverPrice.add(exportDO.getReceiverPrice());
            preReceiverPrice = preReceiverPrice.add(exportDO.getPrepReceiverPrice());
        }
        objs = new Object[rowsName.length];
        objs[0] = doList.size()+1;
        objs[1] = "总计";
        objs[2] = preReceiverPrice;
        objs[3] = receiverPrice;
        dataList.add(objs);
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    public FunctionResult addOrUpdateArapDO(PrepPayDO prepPayDO, String orgId) throws Exception{
        FunctionResult functionResult = new FunctionResult();
        CompanyDealerDO dealerDO;
        dealerDO = companyDealerMapper.item(Long.valueOf(prepPayDO.getCustomerId()));
        if(dealerDO == null){
            LogHelper.error("客户信息不存在，"+dealerDO.getCompanyName(), ErrorCode.Failure.getCode());
            functionResult.setCode(ErrorCode.DealerInfoNotExist);
            functionResult.setValue(ErrorCode.DealerInfoNotExist.getDesc());
            return functionResult;
        }
        ArapDO arapDO = arapMapper.selectByAccOrgId(orgId, dealerDO.getDealerOrgId(), 0);
        if(arapDO == null){
            arapDO = new ArapDO();
            arapDO.setId(fastGenClient.textGuid().getValue());
            arapDO.setOrgId(orgId);
            arapDO.setAccOrgId(dealerDO.getDealerOrgId());
            arapDO.setAccOrgName(dealerDO.getCompanyName());
            arapDO.setDealerCode(dealerDO.getDealerCode());
            arapDO.setArapType(0);
            arapDO.setPrepPayPrice(prepPayDO.getTransactionAmount());
            arapDO.setCreateDate(new Date());
            arapMapper.insert(arapDO);
        }else{
            BigDecimal prepPayPrice = arapDO.getPrepPayPrice().add(prepPayDO.getTransactionAmount());
            int result = prepPayPrice.compareTo(BigDecimal.ZERO);
            if (result < 0 ){
                LogHelper.error("结算卡金额抵扣后为负数", ErrorCode.Failure.getCode());
                functionResult.setCode(ErrorCode.PrepPayTotalAmountLessThanZero);
                functionResult.setValue(ErrorCode.PrepPayTotalAmountLessThanZero.getDesc());
                return functionResult;
            }
            arapDO.setOldPrepPayPrice(arapDO.getPrepPayPrice());
            arapDO.setPrepPayPrice(arapDO.getPrepPayPrice().add(prepPayDO.getTransactionAmount()));
            arapDO.setUpdateDate(new Date());
            int updateResult = arapMapper.updateSelective(arapDO);
            if (updateResult<=0){
                LogHelper.error("结算卡金额更新失败", ErrorCode.Failure.getCode());
                functionResult.setCode(ErrorCode.PrepPayTotalAmountUpdateFailure);
                functionResult.setValue(ErrorCode.PrepPayTotalAmountUpdateFailure.getDesc());
                return functionResult;
            }
        }
        functionResult.setCode(ErrorCode.Success);
        functionResult.setValue(arapDO.getPrepPayPrice());
        return functionResult;

    }

    public CheckVO getPrepPayPrice(String salesBillNo,String orgId){
        CheckVO checkVO = new CheckVO();
        checkVO.setAdvancePayPrice(BigDecimal.ZERO);
        checkVO.setUseVehicleQuota(BigDecimal.ZERO);
        SalesBillDO salesBillDO = salesBillMapper.selectBySalesBillNo(salesBillNo);
        Short giveQuotaType = salesBillDO.getGiveQuotaType();
        ArapDO arapDO = arapMapper.selectByAccOrgId(orgId, salesBillDO.getClientId(), 0);
        if (null != arapDO){
            checkVO.setAdvancePayPrice(arapDO.getPrepPayPrice());
        }
        if (null != giveQuotaType && 0 != giveQuotaType){
            DealerVehicleDO personVehicleInfo = dealerVehicleMapper.getPersonVehicleInfo(salesBillDO.getClientName(), orgId, salesBillDO.getSettleMachineNo());
            if (null == personVehicleInfo){
                checkVO.setUseVehicleQuota(BigDecimal.ZERO);
                checkVO.setUseVehicleQuota(BigDecimal.ZERO);
            }else{
                if (SaleOutEnum.GiveQuotaTypeUniversal.getCode() == giveQuotaType){//通用
                    checkVO.setUseVehicleQuota(personVehicleInfo.getUniversalLaveAmount());
                }
                if (SaleOutEnum.GiveQuotaTypeMaintain.getCode() == giveQuotaType){//保养
                    checkVO.setUseVehicleQuota(personVehicleInfo.getMaintenanceLaveAmount());
                }
            }

        }

        return checkVO;
    }
}
